package com.xbongbong.pro.statistic.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.enums.bi.ChartSourceEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.RegexUtil;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.StatisticsServicesErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.statistic.enums.ChartLimitEnum;
import com.xbongbong.pro.statistic.pojo.DataSourcePojo;
import com.xbongbong.pro.statistic.pojo.DriverSourcePojo;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 图表的工具类
 * @author 梁鲁江
 * @date 2019/1/17 13:47
 * @since v1.0
 * @version v1.0
 */
public class ChartUtil {
    private static final Logger LOG = LoggerFactory.getLogger(ChartUtil.class);

    /**
     * 图表的验证
     * @param entity  图表信息
     * @throws XbbException  异常
     */
    public static void validateLimit(ChartEntity entity) throws XbbException {
        //筛选条件
        arrayLimit(entity.getFilter(), ChartLimitEnum.CHART_FILTER_NUM);
        //查询条件
        arrayLimit(entity.getSearch(), ChartLimitEnum.CHART_SEARCH_NUM);
        if(!Objects.equals(entity.getSingle(), ChartSourceEnum.DATESET.getCode())){
            //驱动表限制
            if(null == entity.getDriverSources()) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, ChartLimitEnum.DRIVER_SOURCE_NUM.getMsg());
            }
            //主表验证
            driverSourceLimit(entity.getDriverSources());
            //从属表数量
            JSONArray slaveSources = entity.getSlaveSources();
//        arrayLimit(slaveSources, ChartLimitEnum.SLAVE_SOURCE_NUM);
            if(null != slaveSources){
                for (Object slaveSource : slaveSources) {
                    dataSourceLimit(new JSONObject((Map<String, Object>) slaveSource) );
                }
            }
        }
        //表头字段
        arrayLimit(entity.getDisplayAttr(), ChartLimitEnum.DISPLAY_SOURCE_NUM);
        //汇总字段
        arrayLimit(entity.getSummaryAttr(), ChartLimitEnum.SUMMARY_SOURCE_NUM);
        //行分组字段
        arrayLimit(entity.getRowGroupAttr(), ChartLimitEnum.GROUP_SOURCE_NUM);
        if (CollectionsUtil.isNotEmpty(entity.getComputedAttr())) {
            checkFormulaStandard(entity.getComputedAttr());
        }
        if (CollectionsUtil.isNotEmpty(entity.getColGroupAttr())) {
            //列分组字段
            arrayLimit(entity.getColGroupAttr(), ChartLimitEnum.GROUP_SOURCE_NUM);
        }
    }

    /**
     * @param conditionJson
     * @return boolean
     * @throws
     * @author gzt
     * @Description 是否公海, 参数conditionJson
     * @Date 8:54 2022/1/17
     * @update 统一移动到ChartUtil中，便于维护
     **/

    public static boolean isPublicFlag(Object conditionJson) {
        if (conditionJson != null) {
            if (conditionJson instanceof JSONObject) {
                if (getPublicFlag((JSONObject) conditionJson)) {
                    return true;
                }
            } else {
                JSONArray jsonArray = (JSONArray) conditionJson;
                for (Object o : jsonArray) {
                    if (getPublicFlag((JSONObject) o)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * @param o
     * @return boolean
     * @throws
     * @author gzt
     * @Description 是否公海, 参数JSONObject
     * @Date 8:56 2022/1/17
     * @update 统一移动到ChartUtil中，便于维护
     **/

    private static boolean getPublicFlag(JSONObject o) {
        JSONObject fJson = o;
        if (fJson != null) {
            Object saasAttr = fJson.get("saasAttr");
            if (saasAttr != null && saasAttr.equals(XbbConstant.IS_PUBLIC)) {
                ConditionsEntityExt condition = JSONObject.parseObject(fJson.toJSONString(), ConditionsEntityExt.class);
                List<Object> value = condition.getValue();
                if (!Objects.isNull(value) && value.size() > 0) {
                    if (Objects.equals(1, value.get(0))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    //-------------------private方法-------------------

    /**
     * 校验计算字段的公式是否规范
     * @param computedAttr  公式数组
     * @throws XbbException 异常
     */
    private static void checkFormulaStandard(JSONArray computedAttr) throws XbbException {
        //遍历每个计算字段
        for (int i = 0; i < computedAttr.size(); i++) {
            JSONObject jsonObject = computedAttr.getJSONObject(i);
            JSONObject formulaInfo = jsonObject.getJSONObject("formulaInfo");
            Integer businessType = jsonObject.getInteger(XbbConstant.BUSINESS_TYPE);
            if (ObjectUtils.isEmpty(formulaInfo)) {
                throw new XbbException(BiErrorCodeEnum.API_ERROR_241018);
            }
            String formula = formulaInfo.getString("formula");
            //先判断text左括号和右括号没有超过10,不能有"、小写字母、汉字
            if (RegexUtil.checkBracketsNumber(formula) || !RegexUtil.checkBracketsMatch(formula) || RegexUtil.checkFormulaSign(formula)
                    || (RegexUtil.checkFormulaStandard(formula) && !Objects.equals(XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode(), businessType))
                    || (RegexUtil.checkWorkOrderV2FormulaStandard(businessType, formula))
            ) {
               throw new XbbException(BiErrorCodeEnum.API_ERROR_241017);
            }
        }
    }

    /**
     * 数据源格式
     * @param driverJson  数据源
     * @throws XbbException 异常
     */
    private static void dataSourceLimit(JSONObject driverJson) throws XbbException {
        if(driverJson != null){
            DataSourcePojo dataSource = JSON.toJavaObject(driverJson, DataSourcePojo.class);
            try {
                if(ReflectHelper.checkObjAllFieldsIsNull(dataSource)){
                    throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, ChartLimitEnum.DATA_SOURCE_FORMART.getMsg());
                }
            } catch (IllegalAccessException e) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, ChartLimitEnum.DATA_SOURCE_FORMART.getMsg());
            }
        }
    }
    /**
     * 数据源格式
     * @param driverJson  数据源
     * @throws XbbException 异常
     */
    private static void driverSourceLimit(JSONObject driverJson) throws XbbException {
        if(driverJson != null){
            DriverSourcePojo dataSource = JSON.toJavaObject(driverJson, DriverSourcePojo.class);
            try {
                if(ReflectHelper.checkObjAllFieldsIsNull(dataSource)){
                    throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, ChartLimitEnum.DATA_SOURCE_FORMART.getMsg());
                }
            } catch (IllegalAccessException e) {
                throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, ChartLimitEnum.DATA_SOURCE_FORMART.getMsg());
            }
        }
    }
    /**
     * 数组长度的验证
     * @param jsonArray  数组
     * @param chartLimitEnum  限制枚举
     * @throws XbbException   异常
     */
    private static void arrayLimit(JSONArray jsonArray, ChartLimitEnum chartLimitEnum) throws XbbException {
        if (jsonArray !=null  && jsonArray.size() > chartLimitEnum.getLimit()) {
            throw new XbbException(StatisticsServicesErrorCodeEnum.API_ERROR_224011, chartLimitEnum.getMsg());
        }
    }
}
